package com.aipsi.cws.supplier.aop;

import com.aipsi.cws.supplier.dvo.CommonVO;
import com.aipsi.cws.supplier.util.ValidatorUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

/**
 * <p>
 *     控制层方法入参校验切面
 * </p>
 * @author 大忽悠
 * @create 2022/4/13 19:54
 */
@Aspect
@Component
public class MethodParamsValidationAspect {
    @Pointcut("execution(* com.aipsi.cws.supplier.controller.*.*(..))")
    public void point(){}

    /**
     * 对方法进行JSR注解的参数校验，如果校验失败，抛出异常
     */
    @Around("point()")
    public Object vaildJSRAnnoAroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        methodParamsValidation(joinPoint);
        return joinPoint.proceed();
    }

    /**
     * 对CommonVO参数校验
     */
    @Around("point()")
    public Object vaildCommonVOAroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
       return CommonVOVaildation(joinPoint);
    }

    private Object CommonVOVaildation(ProceedingJoinPoint joinPoint) throws Throwable {
        //方法传入参数
        Object[] args = joinPoint.getArgs();
        //方法参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        //确定是否存在CommonVO类型的参数,如果存在,再确定该参数的索引位置
        handleCommVO(args, parameterTypes);
        return joinPoint.proceed(args);
    }

    private void methodParamsValidation(ProceedingJoinPoint joinPoint) {
        //方法传入参数
        Object[] args = joinPoint.getArgs();
        //方法
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //当前对象
        Object thisObj = joinPoint.getThis();
        //进行方法参数的类型校验
        ValidatorUtils.doValid(thisObj,method,args);
    }

    private void handleCommVO(Object[] args, Class<?>[] parameterTypes) {
        Integer commonVOIndex = findCommonVOIndex(parameterTypes);
        if(commonVOIndex!=-1)
        {
            CommonVO commonVO = (CommonVO) args[commonVOIndex];
            if(commonVO==null)
            {
                args[commonVOIndex]=new CommonVO();
            }
        }
    }

    private Integer findCommonVOIndex(Class<?>[] parameterTypes) {
        for (int i = 0; i < parameterTypes.length; i++) {
            if(parameterTypes[i].equals(CommonVO.class))
            {
                return i;
            }
        }
        return -1;
    }
}
